package com.svms.indent;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.SerializationUtils;
import org.apache.commons.lang.StringUtils;
import org.zkoss.zhtml.Messagebox;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.sys.ComponentsCtrl;
import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button;
import org.zkoss.zul.Datebox;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listcell;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;

import com.svms.service.constants.SvmsStatusCodes;
import com.svms.service.vo.AddressVO;
import com.svms.service.vo.IndentVO;
import com.svms.service.vo.SpareCodesVO;
import com.svms.service.vo.VehicleSpareVO;
import com.svms.utils.SvmsMessageUtils;
import com.svms.utils.SvmsWindowUtils;
import com.svms.web.constants.SvmsResources;
import com.svms.web.factory.SvmsWebFactory;

/**
 * @author om39a
 * 
 */
public class IndentDialogueCtrl extends GenericForwardComposer<Window> {

	private Window window_indent_dialogue;

	private Button btn_close;
	private Button btn_cancle;
	private Button btn_save_indent;
	private Button btn_edit_indent;
	private Button btn_delete_indent;
	private Button btn_add_indent;

	private Button btn_edit_bill_item;
	private Button btn_add_bill_item;

	private Textbox txb_total_amount;
	private Textbox txb_approval_status;
	private Textbox txb_approval_manager;
	private Textbox txb_shop_address;
	private Textbox txb_shop_name;
	private Textbox txb_indent_id;
	private Datebox dtb_indent_date;
	private Textbox txb_invoice_number;

	public Textbox getTxb_invoice_number() {
		return txb_invoice_number;
	}

	public void setTxb_invoice_number(Textbox txb_invoice_number) {
		this.txb_invoice_number = txb_invoice_number;
	}

	private Datebox dtb_invoice_date;

	private Listbox lstbx_bill_items;

	public Listbox getLstbx_bill_items() {
		if (lstbx_bill_items.getModel() == null) {
			lstbx_bill_items.setModel(new ListModelList<VehicleSpareVO>(
					new ArrayList<VehicleSpareVO>()));
		}
		return lstbx_bill_items;
	}

	public void setLstbx_bill_items(Listbox lstbx_bill_items) {
		this.lstbx_bill_items = lstbx_bill_items;
	}

	private ListModelList<VehicleSpareVO> lst_model_bill_items;

	private IndentVO indentVO;
	private IndentVO oldIndentVO;

	private ManageIndentCtrl manageIndentCtrl;

	public IndentVO getIndentVO() {
		return indentVO;
	}

	public void setIndentVO(IndentVO indentVO) {
		this.indentVO = indentVO;
	}

	public IndentVO getOldIndentVO() {
		return oldIndentVO;
	}

	public void setOldIndentVO(IndentVO oldIndentVO) {
		this.oldIndentVO = (IndentVO) SerializationUtils.clone(oldIndentVO);
	}

	/**
	 * Operation to be performed on load of the window.
	 * 
	 * @param event
	 * @throws Exception
	 */
	public void onCreate$window_indent_dialogue(Event event) throws Exception {

		Map<String, Object> args = SvmsWindowUtils.getCreationArgsMap(event);
		IndentVO selectedIndent = (IndentVO) args.get("selectedIndentDetail");

		indentVO = (IndentVO) SerializationUtils.clone(selectedIndent);
		manageIndentCtrl = (ManageIndentCtrl) args.get("manageIndentCtrl");

		// To populate lst_model_bill_items on startup
		populateBillItemsListBox(selectedIndent);

		setDefaultPageSize();

		if (getIndentVO() == null) {
			// Which means edit in progress. So enable fields to edit
			newIndentDetailMapping();
			setOldIndentVO(getIndentVO());
			loadAddEditScenarioButtons();
			writeBeanToDialogue(getIndentVO());
			enableDefaultFields();
		} else {
			setOldIndentVO(getIndentVO());
			writeBeanToDialogue(getOldIndentVO());
			loadDefalutScenarioButtons();
			disableDefalutFields();
		}

	}

	private void populateBillItemsListBox(IndentVO selectedIndent) {
		if (selectedIndent != null
				&& StringUtils.isNotEmpty(selectedIndent.getIndentId())) {
			lst_model_bill_items = new ListModelList<VehicleSpareVO>(
					indentVO.getBillItems());
		} else {
			lst_model_bill_items = null;
		}
	}

	private void newIndentDetailMapping() {
		IndentVO indentVO = new IndentVO();
		List<VehicleSpareVO> vehicleSpareVOs = new ArrayList<VehicleSpareVO>();
		indentVO.setBillItems(vehicleSpareVOs);
		setIndentVO(indentVO);
	}

	/**
	 * Operation to be performed on click of add spare button. It will
	 * loadAddEditScenarioButtons and enables all editable fields
	 * 
	 * @param event
	 */
	public void onClick$btn_add_indent(Event event) {
		oldIndentVO = null;
		newIndentDetailMapping();
		writeBeanToDialogue(getIndentVO());
		enableDefaultFields();
		loadAddEditScenarioButtons();
	}

	/**
	 * Operation to be performed on click of edit button. It will
	 * loadAddEditScenarioButtons and enables all editable fields
	 * 
	 * @param event
	 */
	public void onClick$btn_edit_indent(Event event) {
		enableDefaultFields();
		loadAddEditScenarioButtons();
	}

	/**
	 * Operation to be performed on click of cancel button. It will
	 * loadDefalutScenarioButtons and disables all editable fields
	 * 
	 * @param event
	 */
	public void onClick$btn_cancle(Event event) {
		writeBeanToDialogue(oldIndentVO);
		setIndentVO(oldIndentVO);
		disableDefalutFields();
		loadDefalutScenarioButtons();
	}

	public void onClick$btn_close(Event event) {
		setIndentVO(oldIndentVO);
		window_indent_dialogue.detach();
	}

	/**
	 * Operation to be performed on click of save button. It performs the save
	 * operation. It will loadDefalutScenarioButtons and disables all editable
	 * fields on successful save
	 * 
	 * @param event
	 */
	public void onClick$btn_save_indent(Event event) {
		doSave();
	}

	/**
	 * Save operation by calling save method from service
	 */
	private void doSave() {

		writeDialogueToBean();

		IndentVO indentVO = null;

		if (StringUtils.isBlank(getIndentVO().getIndentId())) {
			System.out.println("Insert New Indent invoked");

			indentVO = SvmsWebFactory.indentService().insertNewindent(
					getIndentVO());

		} else {
			System.out.println("Save Indent invoked");
			System.out.println("Edit Disabled");

			indentVO = SvmsWebFactory.indentService().editIndent(getIndentVO());

		}

		// Uncomment when adding service call for movement

		/*
		 * if (movementVO.getResultCode().getErrorDetails().size() > 0) {
		 * SvmsMessageUtils.showErrorMessageFromLable(movementVO
		 * .getResultCode().getErrorDetails());
		 * writeBeanToDialogue(getOldMovementVO()); return; }
		 */

		if (false) {

		} else {

			if (manageIndentCtrl.getLstbx_indents() != null) {

				// now synchronize the customer listBox
				ListModelList lml = (ListModelList) manageIndentCtrl
						.getLstbx_indents().getListModel();

				// Check if the customer object is new or updated
				// -1 means that the obj is not in the list, so it's new.
				System.out.println("oldIndentVO " + oldIndentVO);
				System.out.println("getIndentVO " + getIndentVO());
				if (lml.indexOf(oldIndentVO) == -1) {
					lml.add(getIndentVO());
					System.out.println("Add Indent to main vehicle list");
					setOldIndentVO(getIndentVO());
				} else {
					lml.set(lml.indexOf(getOldIndentVO()), getIndentVO());
					System.out.println("save Indent to main vehicle list");
					setOldIndentVO(getIndentVO());
				}

			}
			SvmsMessageUtils
					.showSuccessMessage("Indent Detail Was successfully saved to the system");
			disableDefalutFields();
			loadDefalutScenarioButtons();
		}

		// call from cusromerList then synchronize the customers listBox

	}

	/**
	 * Operation to be performed on click of cancel button. It will
	 * loadDefalutScenarioButtons and disables all editable fields
	 * 
	 * @param event
	 */
	public void onClick$btn_delete_indent(Event event) {

		writeDialogueToBean();

		IndentVO indentVO;

		if (getIndentVO() != null && getIndentVO().getIndentId() != null) {

			indentVO = SvmsWebFactory.indentService().deleteindent(
					getIndentVO());

		} else {
			SvmsMessageUtils
					.showErrorMessageFromLable("There is no indent data to delete");
			return;
		}

		/*
		 * if (getMovementVO().getResultCode().getErrorDetails().size() > 0) {
		 * SvmsMessageUtils.showErrorMessageFromLable(vehicleVO
		 * .getResultCode().getErrorDetails()); return; }
		 */if (false) {
		} else {
			SvmsMessageUtils
					.showSuccessMessage("Indent Detail Was successfully deleted from the System");
			disableDefalutFields();
			loadDefalutScenarioButtons();
		}

		// call from cusromerList then synchronize the customers listBox
		if (manageIndentCtrl.getLstbx_indents() != null) {

			// now synchronize the customer listBox
			final ListModelList lml = (ListModelList) manageIndentCtrl
					.getLstbx_indents().getListModel();

			// Check if the customer object is new or updated
			// -1 means that the obj is not in the list, so it's new.
			if (lml.indexOf(getOldIndentVO()) == -1) {
				System.out
						.println("Spare Indent not present in main Movement list");
			} else {
				lml.remove(getOldIndentVO());
				System.out
						.println("Removed Indent Detail from main Movement list");
			}

		}
		window_indent_dialogue.detach();
	}

	/**
	 * To copy the contents form the individual fields in dialogue box to
	 * service for processing
	 * 
	 * @param vehicleVO
	 */
	private void writeDialogueToBean() {

		indentVO.setIndentId(txb_indent_id.getValue());
		indentVO.setIndentDate(dtb_indent_date.getValue());
		indentVO.setInvoiceNumber(txb_invoice_number.getValue());
		indentVO.setInvoiceDate(dtb_invoice_date.getValue());

		AddressVO addressVO = indentVO.getAddress() == null ? new AddressVO()
				: indentVO.getAddress();
		addressVO.setName(StringUtils.isBlank(txb_shop_name.getValue()) ? null
				: txb_shop_name.getValue());
		addressVO.setAddressLine1(StringUtils.isBlank(txb_shop_address
				.getValue()) ? null : txb_shop_address.getValue());

		indentVO.setAddress(addressVO);
		indentVO.setApproved("APPROVED".equalsIgnoreCase(txb_approval_status
				.getValue()) ? true : false);
		indentVO.setApprovalManager(txb_approval_manager.getValue());
		ListModelList vehicleSpareVOs = (ListModelList) lstbx_bill_items
				.getModel();
		indentVO.setBillItems(vehicleSpareVOs);

		indentVO.setAmount(StringUtils.isBlank(txb_total_amount.getValue()) ? null
				: txb_total_amount.getValue());

		System.out.println("WWWWW");
		System.out.println(vehicleSpareVOs);
		System.out.println("WWWWW");

	}

	private void writeBeanToDialogue(IndentVO indentVO) {

		if (indentVO != null) {

			txb_indent_id.setValue(indentVO.getIndentId());
			dtb_indent_date.setValue(indentVO.getIndentDate());
			txb_invoice_number.setValue(indentVO.getInvoiceNumber());
			dtb_invoice_date.setValue(indentVO.getInvoiceDate());
			if (indentVO.getAddress() != null) {
				txb_shop_name.setValue(indentVO.getAddress().getName());
				txb_shop_address.setValue(indentVO.getAddress()
						.getAddressLine1());
			}
			txb_approval_manager.setValue(indentVO.getApprovalManager());
			txb_approval_status.setValue(indentVO.isApproved() ? "Approved"
					: "Not Approved");

			populateBillItemsListBox(indentVO);

			lstbx_bill_items.setModel(lst_model_bill_items);
			lstbx_bill_items
					.setItemRenderer(new ListitemRenderer<VehicleSpareVO>() {

						@Override
						public void render(Listitem item, VehicleSpareVO data,
								int index) throws Exception {

							Listcell listcell = new Listcell(data
									.getVehicleVO().getVehicleId());
							listcell.setParent(item);
							listcell = new Listcell(data.getVehicleVO()
									.getTransport().getCompanyName());
							listcell.setParent(item);
							listcell = new Listcell(data.getSpareCodes()
									.getSpareName());
							listcell.setParent(item);
							listcell = new Listcell(data.getVehicleSpareCost());
							listcell.setParent(item);
							listcell = new Listcell(formatDate(data
									.getInstallationDate()));
							listcell.setParent(item);

							item.setAttribute("selectedBillItem", data);

							ComponentsCtrl.applyForward(item,
									"onDoubleClick=onBillItemDoubleClicked");

						}

						private String formatDate(Date date) {
							String formatedDate = null;
							if (date != null) {
								SimpleDateFormat dateFormat = new SimpleDateFormat(
										"dd-MMM-yyyy");
								formatedDate = dateFormat.format(date);
							}
							return formatedDate;
						}
					});

		}
	}

	/**
	 * To perform the double click event on the bill list
	 * 
	 * @param event
	 * @throws Exception
	 */
	public void onBillItemDoubleClicked(Event event) throws Exception {

		Messagebox
				.show("To edit this record, click on \"Edit Bill Item\" button");

	}

	private void loadEditBillItemWindow() {
		Listitem item = this.lstbx_bill_items.getSelectedItem();

		if (item != null) {
			VehicleSpareVO vehicleSpare = (VehicleSpareVO) item
					.getAttribute("selectedBillItem");
			System.out.println("...............");
			System.out.println(vehicleSpare);
			System.out.println("...............");
			showDetailView(vehicleSpare);
		}
	}

	/**
	 * Opens the detail view of the Vehicle Controller. <br>
	 * Overhanded some params in a map if needed. <br>
	 * 
	 * @param branche
	 * @throws Exception
	 */
	private void showDetailView(VehicleSpareVO vehicleSpare) {

		final HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("selectedBillItem", vehicleSpare);
		map.put("indentDialogueCtrl", this);
		Window win = null;
		try {
			win = (Window) Executions.createComponents(
					SvmsResources.MANAGE_BILL_ITEM_DIALOGUE, null, map);
		} catch (final Exception e) {
			e.printStackTrace();
			SvmsMessageUtils.showErrorMessage(e.getMessage());
			if (win != null) {
				win.detach();
			}
		}
	}

	private void loadAddEditScenarioButtons() {

		btn_add_indent.setDisabled(true);
		btn_delete_indent.setDisabled(true);
		btn_edit_indent.setDisabled(true);
		btn_save_indent.setDisabled(false);

		btn_cancle.setDisabled(false);
		btn_close.setDisabled(false);

	}

	private void enableDefaultFields() {

		txb_approval_manager.setDisabled(false);
		txb_approval_status.setDisabled(false);
		txb_indent_id.setDisabled(false);
		txb_invoice_number.setDisabled(false);
		txb_shop_address.setDisabled(false);
		txb_shop_name.setDisabled(false);
		txb_total_amount.setDisabled(false);

		dtb_indent_date.setDisabled(false);
		dtb_invoice_date.setDisabled(false);

		lstbx_bill_items.setDisabled(false);

		// Bill item fields

		btn_add_bill_item.setDisabled(false);
		btn_edit_bill_item.setDisabled(false);
		lstbx_bill_items.setDisabled(false);

	}

	private void disableDefalutFields() {

		txb_approval_manager.setDisabled(true);
		txb_approval_status.setDisabled(true);
		txb_indent_id.setDisabled(true);
		txb_invoice_number.setDisabled(true);
		txb_shop_address.setDisabled(true);
		txb_shop_name.setDisabled(true);
		txb_total_amount.setDisabled(true);

		dtb_indent_date.setDisabled(true);
		dtb_invoice_date.setDisabled(true);

		// Bill item fields

		btn_add_bill_item.setDisabled(true);
		btn_edit_bill_item.setDisabled(true);
		lstbx_bill_items.setDisabled(true);

	}

	/**
	 * Will load DEFAULT CURD buttons. Is same for DEFALUT, SAVE, DISCARD
	 */
	private void loadDefalutScenarioButtons() {

		btn_add_indent.setDisabled(false);
		btn_delete_indent.setDisabled(false);
		btn_edit_indent.setDisabled(false);
		btn_save_indent.setDisabled(true);

		btn_cancle.setDisabled(true);
		btn_close.setDisabled(false);

		// Bill item fields

		btn_add_bill_item.setDisabled(true);
		btn_edit_bill_item.setDisabled(true);
		lstbx_bill_items.setDisabled(true);

	}

	private void setDefaultPageSize() {
		lstbx_bill_items.setMold("paging");
		lstbx_bill_items.setPageSize(5);
	}

	public void onClick$btn_add_bill_item(Event event) {
		showDetailView(null);
	}

	public void onClick$btn_edit_bill_item(Event event) {
		loadEditBillItemWindow();
	}

}
